home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / OpenGL / stonehenge / callbacks.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  10.6 KB  |  463 lines

  1. /*
  2.  * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  * Permission to use, copy, modify, and distribute this software for
  5.  * any purpose and without fee is hereby granted, provided that the above
  6.  * copyright notice appear in all copies and that both the copyright notice
  7.  * and this permission notice appear in supporting documentation, and that
  8.  * the name of Silicon Graphics, Inc. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.
  11.  *
  12.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  16.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  21.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25.  * US Government Users Restricted Rights
  26.  * Use, duplication, or disclosure by the Government is subject to
  27.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29.  * clause at DFARS 252.227-7013 and/or in similar or successor
  30.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  31.  * Unpublished-- rights reserved under the copyright laws of the
  32.  * United States.  Contractor/manufacturer is Silicon Graphics,
  33.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  34.  *
  35.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  36.  */
  37. #include <X11/Intrinsic.h>
  38. #include <X11/keysym.h>
  39. #include <Xm/Xm.h>
  40.  
  41. #include <GL/glu.h>
  42. #include <GL/glx.h>
  43. #include <GLwMDrawA.h>
  44.  
  45. #include <math.h>
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <sys/time.h>
  49.  
  50. #include "atmosphere.h"
  51. #include "scene.h"
  52.  
  53. #include "callbacks.h"
  54.  
  55. int cb_demo_mode = 0;
  56. float demo_time;
  57.  
  58. extern Widget glw;
  59. extern XtAppContext app_context;
  60. GLXContext glx_context;
  61.  
  62. static int needs_wp = 0;
  63. static XtWorkProcId workproc = NULL;
  64.  
  65. static int winx, winy;
  66.  
  67. static int button_down = 0;
  68. int mousex, mousey;
  69. /* What's moving */
  70. GLint target;
  71.  
  72. /* Location of the telescope */
  73. GLfloat tx, ty;
  74.  
  75. /* Movements of the camera position to be applied at the next redraw */
  76. float rot_pendx = 0, rot_pendz = 0, trans_pend = 0;
  77.  
  78. /* How fast the camera is moving */
  79. float trans_speed = 0;
  80.  
  81. /* This is how fast demo time moves relative to real time */
  82. GLfloat time_scale = 0;
  83.  
  84. TimeDate last_update;
  85.  
  86. float last_time = 0;
  87. const float time_fudge = 1000;
  88. inline unsigned long current_time()
  89. {
  90.   struct timeval time;
  91.   gettimeofday(&time, NULL);
  92.   return (time.tv_sec * 1000000 + time.tv_usec);
  93. }
  94.  
  95. inline float clamp(float x, float min, float max)
  96. {
  97.   if (x < min) return min;
  98.   else if (x > max) return max;
  99.   else return x;
  100. }
  101.  
  102. static void add_workproc()
  103. {
  104.   needs_wp++;
  105.   if (workproc == NULL)
  106.     workproc = XtAppAddWorkProc(app_context, drawWP, NULL);
  107. }
  108.  
  109. static void remove_workproc()
  110. {
  111.   needs_wp--;
  112.   if (needs_wp == 0) {
  113.     XtRemoveWorkProc(workproc);
  114.     workproc = NULL;
  115.   } else if (needs_wp < 0) {
  116.     fprintf(stderr, "Internal Error:  No workproc to remove!\n");
  117.     needs_wp = 0;
  118.     workproc = NULL;
  119.   }
  120. }
  121.  
  122. static void reset_viewer()
  123. {
  124.   scene_viewer_center();
  125. }
  126.  
  127. void intToggleCB(Widget w, XtPointer client_data, XtPointer call_data)
  128. {
  129.   int *data;
  130.   XmToggleButtonCallbackStruct *ptr;
  131.   ptr = (XmToggleButtonCallbackStruct *)call_data;
  132.   data = (int *)client_data;
  133.   *data = ptr->set;
  134.   // This redraw may or may not be needed - do it to be safe
  135.   drawWP(NULL);
  136. }
  137.  
  138.  
  139. void initCB(Widget w)
  140. {
  141.   Arg args[1];
  142.   XVisualInfo *vi;
  143.  
  144.   glw = w;
  145.  
  146.   XtSetArg(args[0], GLwNvisualInfo, &vi);
  147.   XtGetValues(w, args, 1);
  148.  
  149.   glx_context = glXCreateContext(XtDisplay(w), vi, 0, GL_FALSE);
  150.   GLwDrawingAreaMakeCurrent(w, glx_context);
  151.  
  152.   scene_init();
  153.  
  154.   last_update.read_time();
  155.  
  156.   resetViewerCB(NULL, NULL, NULL);
  157. }
  158.  
  159. void exposeCB(Widget w)
  160. {
  161.   drawWP(NULL);
  162. }
  163.  
  164. void resizeCB(Widget w, XtPointer client_data, XtPointer call)
  165. {
  166.   GLwDrawingAreaCallbackStruct *call_data;
  167.  
  168.   GLwDrawingAreaMakeCurrent(w, glx_context);
  169.  
  170.   call_data = (GLwDrawingAreaCallbackStruct *)call;
  171.  
  172.   winx = call_data->width;
  173.   winy = call_data->height;
  174.   
  175.   glViewport(0, 0, winx, winy);
  176.   
  177.   aspect = (GLfloat)winx / (GLfloat)winy;
  178. }
  179.  
  180. void inputCB(Widget w, XtPointer client_data, XtPointer call_data)
  181. {
  182.   GLwDrawingAreaCallbackStruct *call;
  183.  
  184.   char buffer[5];
  185.   int bufsize = 5;
  186.   KeySym key;
  187.   XComposeStatus compose;
  188.  
  189.   float dx, dy, r1, r2;
  190.  
  191.   GLwDrawingAreaMakeCurrent(w, glx_context);
  192.  
  193.   call = (GLwDrawingAreaCallbackStruct *)call_data;
  194.  
  195.   switch(call->event->type) {
  196.   case ButtonPress:
  197.     last_time = current_time();
  198.     button_down = call->event->xbutton.button;
  199.     mousex = call->event->xbutton.x;
  200.     mousey = call->event->xbutton.y;
  201.     /* Determine if the target should be the camera position 
  202.      * or the telescope */
  203.     if (use_telescope) {
  204.       scene_get_position_telescope(&tx, &ty);
  205.       scene_get_radius_telescope(&r1);
  206.       dx = (tx + .5) - ((GLfloat)(winx - mousex)/(GLfloat)winx);
  207.       dy = (ty + .5) - ((GLfloat)(winy - mousey)/(GLfloat)winy);
  208.       r2 = sqrt(dx*dx + dy*dy);
  209.       if (r2 < r1) target = name_telescope;
  210.       else target = name_background;
  211.     } else target = name_background;
  212.     add_workproc();
  213.     break;
  214.   case ButtonRelease:
  215.     if (call->event->xbutton.button == Button3) {
  216.       /* Use Button3 to stop */
  217.       if (trans_speed) remove_workproc();
  218.       trans_speed = 0;
  219.     }
  220.     remove_workproc();
  221.     button_down = 0;
  222.     break;
  223.   case MotionNotify:
  224.     switch(button_down) {
  225.     case Button1:
  226.       /* Use Button1 to control the way in which the viewer is looking 
  227.        * or to move the telescope around */
  228.       if (target == name_background) {
  229.     dx = (float)(call->event->xmotion.x - mousex) / (float)winx;
  230.     dy = (float)(call->event->xmotion.y - mousey) / (float)winy;
  231.     rot_pendx -= dy * fov;
  232.     rot_pendz -= dx * fov;
  233.       } else {
  234.     dx = (float)(mousex - call->event->xmotion.x) / (float)winx;
  235.     dy = (float)(mousey - call->event->xmotion.y) / (float)winy;
  236.     tx += dx;
  237.     ty += dy;
  238.     tx = clamp(tx, -.5, .5);
  239.     ty = clamp(ty, -.5, .5);
  240.     scene_position_telescope(tx, ty);
  241.       }
  242.       break;
  243.     case Button2:
  244.       /* Use Button2 to change speed */
  245.       dx = (float)(mousex - call->event->xmotion.x) / 
  246.     (float)winx;
  247.       if (dx && !trans_speed) add_workproc();
  248.       else if (!dx && trans_speed) remove_workproc();
  249.       trans_speed += dx;
  250.       break;
  251.     }
  252.     mousex = call->event->xmotion.x;
  253.     mousey = call->event->xmotion.y;
  254.     break;
  255.   case KeyPress:
  256.     XLookupString(&(call->event->xkey), buffer, bufsize, &key, &compose);
  257.     if (key == XK_Escape) exit(0);
  258.     break;                            
  259.   default:
  260.     break;
  261.   }
  262. }
  263.  
  264. const float speed_t = .5;
  265. const float speed_r = 15.;
  266. const float speed_rx = 10.;
  267. void demo_mode_update(float dt)
  268. {
  269.   float t;
  270.   
  271.   if (!cb_demo_mode) return;
  272.   
  273.   dt /= 1000000;
  274.   demo_time += dt;
  275.   
  276.   t = demo_time;
  277.   
  278.   if (t < 10.5) {
  279.     trans_speed = speed_t;
  280.     return;
  281.   } else t -= 10.5;
  282.   
  283.   if (t < 1) {
  284.     trans_speed = 0;
  285.     rot_pendz = 0;
  286.     return;
  287.   } else t -= 1;
  288.   
  289.   if (t < 3.) {
  290.     trans_speed = 0.;
  291.     rot_pendz = dt * speed_r;
  292.     return;
  293.   } else t -= 3.;
  294.   
  295.   if (t < 2.) {
  296.     rot_pendx = -dt * speed_rx;
  297.     return;
  298.   } else t -= 2.;
  299.  
  300.   if (t < 2.) {
  301.     return;
  302.   } else t -= 2.;
  303.  
  304.   if (t < 2.) {
  305.     rot_pendx = dt * speed_rx;
  306.     return;
  307.   } else t -= 2.;
  308.   
  309.  
  310.   if (t < 3.) {
  311.     trans_speed = 0.;
  312.     rot_pendz = dt * speed_r;
  313.     return;
  314.   } else t -= 3.;
  315.  
  316.   if (t < 30.) {
  317.     trans_speed  = speed_t;
  318.     rot_pendz = 0;
  319.     return;
  320.   } else t -= 30.;
  321.   
  322.   if (t < 1.) {
  323.     trans_speed = 0;
  324.     return;
  325.   } else t -= 1.;
  326.  
  327.   if (t < 1.3) {
  328.     rot_pendz = -dt * speed_r;
  329.     return;
  330.   } else t -= 1.3;
  331.  
  332.   // Pan back to see entire thing
  333.   if (t < 23) {
  334.     trans_speed = speed_t;
  335.     return;
  336.   } else t -= 23;
  337.  
  338.   // Hold before starting over
  339.   if (t < 20) {
  340.     trans_speed = 0;
  341.     return;
  342.   }
  343.   else t -= 20;
  344.  
  345.   demo_time = 0.;
  346.   reset_viewer();
  347. }
  348.  
  349. Boolean drawWP(XtPointer data)
  350. {
  351.   /* Right now, there's two completely independent time measurements:
  352.    * one for the time of day in the demo and one for changing the camera
  353.    * position */
  354.   TimeDate t, dt;
  355.   float elapsed_time, time;
  356.  
  357.   if (time_scale != 0.0) {
  358.     t.read_time();
  359.     dt = (t - last_update) * time_scale;
  360.     scene_inc_time(dt);
  361.     last_update = t;
  362.   }
  363.  
  364.   time = current_time();
  365.   if (time - last_time > time_fudge) {
  366.     elapsed_time = time - last_time;
  367.     demo_mode_update(elapsed_time);
  368.     trans_pend = trans_speed * (elapsed_time / 1000000);
  369.     last_time = time;
  370.   }
  371.  
  372.   scene_viewer_rotatex(rot_pendx);
  373.   scene_viewer_rotatez(rot_pendz);
  374.   scene_viewer_translate(trans_pend);
  375.   rot_pendx = 0;
  376.   rot_pendz = 0;
  377.   trans_pend = 0;
  378.  
  379.   GLwDrawingAreaMakeCurrent(glw, glx_context);
  380.   scene_render();
  381.   /* This is a total hack */
  382. //  if (!use_antialias)
  383. GLwDrawingAreaSwapBuffers(glw);
  384.  
  385.   return FALSE;
  386. }
  387.  
  388. void weatherCB(Widget w, XtPointer client_data, XtPointer call_data)
  389. {
  390.   Weather *data;
  391.   XmToggleButtonCallbackStruct *ptr;
  392.   ptr = (XmToggleButtonCallbackStruct *)call_data;
  393.   if (ptr->set) scene_set_weather(*((Weather *)client_data));
  394.   drawWP(NULL);
  395. }
  396.  
  397. void currentTimeCB(Widget w)
  398. {
  399.   scene_set_time(TimeDate().read_time());
  400.   drawWP(NULL);
  401. }
  402.  
  403. void time10amCB(Widget w)
  404. {
  405.   scene_set_time(TimeDate(10, 0));
  406.   drawWP(NULL);
  407. }
  408.  
  409. void time12pmCB(Widget w)
  410. {
  411.   scene_set_time(TimeDate(12, 0));
  412.   drawWP(NULL);
  413. }
  414.  
  415. void time4pmCB(Widget w)
  416. {
  417.   scene_set_time(TimeDate(16, 0));
  418.   drawWP(NULL);
  419. }
  420.  
  421. void timeSpeedCB(Widget w, XtPointer client_data, XtPointer call_data)
  422. {
  423.   
  424.   if (!((XmToggleButtonCallbackStruct *)call_data)->set) return;
  425.   time_scale = (int)client_data;
  426.   if (time_scale == 0.0) remove_workproc();
  427.   else add_workproc();
  428.   last_update.read_time();
  429. }
  430.  
  431. void demo_modeCB(Widget w, XtPointer client_data, XtPointer call_data)
  432. {
  433.   int val  = ((XmToggleButtonCallbackStruct *)call_data)->set;
  434.   if (!val) {
  435.     remove_workproc();
  436.     resetViewerCB(NULL, NULL, NULL);
  437.     last_time = current_time();
  438.   } else {
  439.     reset_viewer();
  440.     add_workproc();
  441.     trans_speed = 0;
  442.     demo_time = 0;
  443.     rot_pendx = -5;
  444.   }
  445.   cb_demo_mode = val;
  446.   drawWP(NULL);
  447. }
  448.  
  449. void resetViewerCB(Widget w, XtPointer client_data, XtPointer call_data)
  450. {
  451.   trans_speed = 0;
  452.   rot_pendx = rot_pendz = trans_pend = 0;
  453.   rot_pendx = -5;
  454.   reset_viewer();
  455.   return;
  456. }
  457.      
  458.  
  459. void exitCB(Widget w, XtPointer client_data, XtPointer call_data)
  460. {
  461.   exit(0);
  462. }
  463.